package com.gengzp.system.service.impl;

import com.gengzp.common.enums.ConsolePageEnum;
import com.gengzp.common.enums.GenderEnum;
import com.gengzp.common.enums.PermissionEnum;
import com.gengzp.common.enums.YesNoEnum;
import com.gengzp.common.exception.BusinessException;
import com.gengzp.common.model.pagination.resp.PaginationResponse;
import com.gengzp.common.model.permission.dto.ConsolePageDto;
import com.gengzp.common.model.permission.dto.PermissionDto;
import com.gengzp.common.model.permission.dto.SysUserRelationRoleDto;
import com.gengzp.common.model.role.entity.SysRole;
import com.gengzp.common.model.user.entity.SysUser;
import com.gengzp.common.model.user.req.CreateSysUserReq;
import com.gengzp.common.model.user.req.EditSysUserPasswordReq;
import com.gengzp.common.model.user.req.EditSysUserReq;
import com.gengzp.common.model.user.req.PageSysUserReq;
import com.gengzp.common.model.user.resp.PageUserResp;
import com.gengzp.common.model.user.resp.SearchSysUserResp;
import com.gengzp.common.utils.EncryptionUtils;
import com.gengzp.common.utils.ThreadUtils;
import com.gengzp.permission.utils.PermissionUtils;
import com.gengzp.system.facade.PermissionFacade;
import com.gengzp.system.facade.SysRoleFacade;
import com.gengzp.system.mapper.SysUserMapper;
import com.gengzp.system.service.SysUserService;
import com.gengzp.system.utils.OperatorInfoUtils;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName SysUserServiceImpl
 * @Description 系统用户管理模块服务层实现
 * @Author gengzp
 * @Date 2025/9/19 13:37
 */
@Service
public class SysUserServiceImpl implements SysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysRoleFacade sysRoleFacade;

    @Autowired
    private PermissionFacade permissionFacade;

    /**
     * 系统默认用户密码
     */
    private static final String DEFAULT_USER_PASSWORD = "88888888";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createSysUser(CreateSysUserReq req) {
        // 账号昵称防重
        List<String> errorMessages = ThreadUtils.batchExecute(() -> {
            if (Objects.equals(req.getUserAccount(), PermissionUtils.getSuperAdminUserAccount()) ||
                    Objects.nonNull(sysUserMapper.selectSysUserByAccount(req.getUserAccount()))) {
                throw BusinessException.get("当前用户账号【】已被占用，无法重复创建");
            }
        }, () -> {
            if (Objects.equals(req.getUserNickname(), PermissionUtils.getSuperAdminNickname()) ||
                    Objects.nonNull(sysUserMapper.selectSysUserByNickname(req.getUserNickname()))) {
                throw BusinessException.get("当前用户昵称【】已被占用，无法重复创建");
            }
        });
        if (CollectionUtils.isNotEmpty(errorMessages)) {
            throw BusinessException.get(StringUtils.join(errorMessages, "；"));
        }

        SysUser sysUser = new SysUser();
        sysUser.setUserAccount(req.getUserAccount());
        sysUser.setUserNickname(req.getUserNickname());
        sysUser.setUserGender(req.getUserGender());
        sysUser.setIsDeleted(YesNoEnum.NO.getCode());
        // 填充默认密码
        sysUser.setSalt(UUID.randomUUID().toString().replace("-", ""));
        sysUser.setUserPassword(EncryptionUtils.md5hex(DEFAULT_USER_PASSWORD + sysUser.getSalt()));
        sysUserMapper.insertSysUser(sysUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editSysUserById(EditSysUserReq req) {
        if (Objects.equals(req.getId(), PermissionUtils.getSuperAdminUserId())) {
            throw BusinessException.get("超级管理员用户信息不允许修改");
        }

        SysUser sysUser = sysUserMapper.selectSysUserById(Long.valueOf(req.getId()));
        if (Objects.isNull(sysUser)) {
            throw BusinessException.get("当前用户已不存在");
        }

        if (Objects.equals(req.getUserNickname(), PermissionUtils.getSuperAdminNickname())) {
            throw BusinessException.get("当前用户昵称【】已被占用，无法修改");
        }
        SysUser sysUserByNickname = sysUserMapper.selectSysUserByNickname(req.getUserNickname());
        if (Objects.nonNull(sysUserByNickname) && !Objects.equals(sysUser.getId(), sysUserByNickname.getId())) {
            throw BusinessException.get("当前用户昵称【】已被占用，无法修改");
        }

        sysUser.setUserNickname(req.getUserNickname());
        sysUser.setUserGender(req.getUserGender());
        sysUser.setUserIntroduction(req.getUserIntroduction());
        sysUserMapper.updateSysUserById(sysUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editSysUserPasswordById(EditSysUserPasswordReq req) {
        if (Objects.equals(req.getId(), PermissionUtils.getSuperAdminUserId())) {
            throw BusinessException.get("超级管理员用户信息不允许修改");
        }

        SysUser sysUser = sysUserMapper.selectSysUserById(Long.valueOf(req.getId()));
        if (Objects.isNull(sysUser)) {
            throw BusinessException.get("当前用户已不存在");
        }

        // 新密码盐值加密
        String newPassword = EncryptionUtils.md5hex(req.getNewPassword() + sysUser.getSalt());
        if (!Objects.equals(newPassword, sysUser.getUserPassword())) {
            throw BusinessException.get("原密码错误");
        }

        sysUser.setUserPassword(newPassword);
        sysUserMapper.updateSysUserById(sysUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeSysUserById(Long userId) {
        if (Objects.equals(String.valueOf(userId), PermissionUtils.getSuperAdminUserId())) {
            throw BusinessException.get("超级管理员用户不允许删除");
        }

        // 删除用户
        sysUserMapper.deleteSysUserById(userId);
        // 删除用户角色关联关系
        permissionFacade.removeUserRoleRelationsByUserId(userId);
    }

    @Override
    public SearchSysUserResp searchSysUserById(Long userId) {
        SearchSysUserResp resp = new SearchSysUserResp();

        // 超级管理员数据直接从框架中读取
        if (Objects.equals(String.valueOf(userId), PermissionUtils.getSuperAdminUserId())) {
            resp = buildSuperAdminSearchSysUserResp();
        } else {
            // 非超级管理员直接从数据库读取
            SysUser sysUser = sysUserMapper.selectSysUserById(userId);
            if (Objects.isNull(sysUser)) {
                throw BusinessException.get("当前用户已不存在");
            }
            // 组装返回实体
            fillInSysUserInformation2SearchResp(sysUser, resp);
        }

        // 填充操作人信息
        OperatorInfoUtils.fillInGenericRespOperatorInformation(resp);

        // 补全权限集合信息
        resp.setRelationPermissions(
                CollectionUtils.isEmpty(resp.getRelationPermissions()) ?
                        Lists.newArrayList() :
                        resp.getRelationPermissions().stream().map(v -> {
                            PermissionEnum permissionEnum = PermissionEnum.getByCode(v.getPermissionCode());
                            if (Objects.isNull(permissionEnum)) {
                                return null;
                            }
                            v.setPermissionName(permissionEnum.getName());
                            v.setPermissionDescription(permissionEnum.getDescription());
                            return v;
                        }).filter(Objects::nonNull).collect(Collectors.toList())
        );

        // 补全页面信息集合
        resp.setConsolePages(
                CollectionUtils.isEmpty(resp.getConsolePages()) ?
                        Lists.newArrayList() :
                        resp.getConsolePages().stream().map(v -> {
                            ConsolePageEnum consolePageEnum = ConsolePageEnum.getByCode(v.getPageCode());
                            if (Objects.isNull(consolePageEnum)) {
                                return null;
                            }
                            v.setPageName(consolePageEnum.getName());
                            v.setModule(consolePageEnum.getModule());
                            return v;
                        }).filter(Objects::nonNull).collect(Collectors.toList())
        );

        return resp;
    }

    @Override
    public PaginationResponse<PageUserResp> pageQuerySysUser(PageSysUserReq req) {
        List<PageUserResp> result = Lists.newArrayList();

        // 先处理根据角色查询的情况
        if (StringUtils.isNotBlank(req.getRoleName())) {
            SysRole sysRole = sysRoleFacade.searchSysRoleByRoleName(req.getRoleName());
            if (Objects.isNull(sysRole)) {
                return PaginationResponse.get(result, req);
            }
            // 根据角色查询出绑定的用户id
            List<Long> roleRelationUserIds = permissionFacade.searchUserIdsByRoleId(sysRole.getId());
            if (CollectionUtils.isEmpty(roleRelationUserIds)) {
                return PaginationResponse.get(result, req);
            }
            req.setUserIds(roleRelationUserIds);
        }

        List<SysUser> sysUsers = sysUserMapper.pageQuerySysUser(req);
        if (CollectionUtils.isEmpty(sysUsers)) {
            return PaginationResponse.get(Lists.newArrayList(), req);
        }

        for (SysUser sysUser : sysUsers) {
            PageUserResp resp = new PageUserResp();
            resp.setId(String.valueOf(sysUser.getId()));
            resp.setUserAccount(sysUser.getUserAccount());
            resp.setUserNickname(sysUser.getUserNickname());
            resp.setUserGender(sysUser.getUserGender());
            resp.setUserGenderValue(GenderEnum.getValueByCode(sysUser.getUserGender()));
            resp.setUserIntroduction(sysUser.getUserIntroduction());
            resp.setCreatedBy(String.valueOf(sysUser.getCreatedBy()));
            resp.setCreatedTime(sysUser.getCreatedTime());
            resp.setLastModifiedBy(String.valueOf(sysUser.getLastModifiedBy()));
            resp.setLastModifiedTime(sysUser.getLastModifiedTime());
            result.add(resp);
        }
        // 填充操作人
        OperatorInfoUtils.fillInGenericRespOperatorInformation(result);

        return PaginationResponse.get(result, req);
    }

    /**
     * 组装超级管理员的查询用户详情返回实体
     *
     * @return 查询用户详情返回实体
     */
    private SearchSysUserResp buildSuperAdminSearchSysUserResp() {
        SearchSysUserResp resp = new SearchSysUserResp();
        resp.setId(PermissionUtils.getSuperAdminUserId());
        resp.setUserAccount(PermissionUtils.getSuperAdminUserAccount());
        resp.setUserNickname(PermissionUtils.getSuperAdminNickname());
        resp.setUserGender(GenderEnum.MAN.getCode());
        resp.setUserGenderValue(GenderEnum.MAN.getValue());
        resp.setUserIntroduction("系统超级管理员账号， 拥有系统所有数据的管理权限。");
        resp.setCreatedBy(PermissionUtils.getSuperAdminUserId());
        resp.setLastModifiedBy(PermissionUtils.getSuperAdminUserId());
        Date operateDate = new Date(0);
        resp.setCreatedTime(operateDate);
        resp.setLastModifiedTime(operateDate);
        resp.setRelationRoleDtos(Lists.newArrayList());
        resp.setRelationPermissions(Lists.newArrayList());
        List<SysRole> sysRoles = sysRoleFacade.searchAllSysRoles();
        if (CollectionUtils.isNotEmpty(sysRoles)) {
            resp.setRelationRoleDtos(sysRoles.stream().map(v -> {
                SysUserRelationRoleDto dto = new SysUserRelationRoleDto();
                dto.setRoleId(String.valueOf(v.getId()));
                dto.setRoleName(v.getRoleName());
                return dto;
            }).collect(Collectors.toList()));
        }

        List<String> permissionNames = permissionFacade.searchAllLeafPermissionCodes();
        if (CollectionUtils.isNotEmpty(permissionNames)) {
            resp.setRelationPermissions(permissionNames.stream().map(v -> {
                PermissionDto dto = new PermissionDto();
                dto.setPermissionCode(v);
                return dto;
            }).collect(Collectors.toList()));
        }

        List<String> consolePageCodes = permissionFacade.searchAllConsolePageCodes();
        if (CollectionUtils.isNotEmpty(consolePageCodes)) {
            resp.setConsolePages(consolePageCodes.stream().map(v -> {
                ConsolePageDto dto = new ConsolePageDto();
                dto.setPageCode(v);
                return dto;
            }).collect(Collectors.toList()));
        }

        return resp;
    }

    /**
     * 填充系统用户基础信息到查询用户详情返回实体
     *
     * @param sysUser 系统用户对象
     * @param resp    查询用户详情返回实体
     */
    private void fillInSysUserInformation2SearchResp(SysUser sysUser, SearchSysUserResp resp) {
        // 填充基础信息
        resp.setId(String.valueOf(sysUser.getId()));
        resp.setUserAccount(sysUser.getUserAccount());
        resp.setUserNickname(sysUser.getUserNickname());
        resp.setUserGender(sysUser.getUserGender());
        resp.setUserGenderValue(GenderEnum.getValueByCode(sysUser.getUserGender()));
        resp.setUserIntroduction(sysUser.getUserIntroduction());
        resp.setCreatedBy(String.valueOf(sysUser.getCreatedBy()));
        resp.setCreatedTime(sysUser.getCreatedTime());
        resp.setLastModifiedBy(String.valueOf(sysUser.getLastModifiedBy()));
        resp.setLastModifiedTime(sysUser.getLastModifiedTime());
        resp.setRelationRoleDtos(Lists.newArrayList());
        resp.setRelationPermissions(Lists.newArrayList());

        // 填充角色及权限信息
        List<Long> roleIds = permissionFacade.searchRoleIdsByUserId(sysUser.getId());
        if (CollectionUtils.isEmpty(roleIds)) {
            return;
        }
        List<SysRole> sysRoles = sysRoleFacade.searchSysRolesByIds(roleIds);
        if (CollectionUtils.isEmpty(sysRoles)) {
            return;
        }

        resp.setRelationRoleDtos(sysRoles.stream().map(v -> {
            SysUserRelationRoleDto dto = new SysUserRelationRoleDto();
            dto.setRoleId(String.valueOf(v.getId()));
            dto.setRoleName(v.getRoleName());
            return dto;
        }).collect(Collectors.toList()));

        resp.setRelationPermissions(
                sysRoles.stream().map(v -> v.getPermissionCodes().split(","))
                        .flatMap(Arrays::stream).filter(StringUtils::isNotBlank).distinct().map(v -> {
                            PermissionDto dto = new PermissionDto();
                            dto.setPermissionCode(v);
                            return dto;
                        }).collect(Collectors.toList()));

        resp.setConsolePages(
                sysRoles.stream().map(v -> v.getConsolePageCodes().split(","))
                        .flatMap(Arrays::stream).filter(StringUtils::isNotBlank).distinct().map(v -> {
                            ConsolePageDto dto = new ConsolePageDto();
                            dto.setPageCode(v);
                            return dto;
                        }).collect(Collectors.toList()));
    }

}
